1

laravel5.1 基于redis实现任务队列

1、服务器配置redis

以ubuntu为例:

1、安装redis

$ sudo apt-get install redis-server

安装完成后可以使用以下命令查看redis服务是否启动

$ ps aux | grep redis

如果没有,则输入

$ sudo service redis-server start

启动后,使用

$ redis-cli

进入redis命令行,可以用以下命令行测试存储

$ set test "hello word"
$ get test

2、配置redis

配置远程登录,默认redis是不允许远程登录的,需要我们配置,

==但如果应用服务器和redis安装在同个服务器中,则不需要做这一步。==

#编辑redis配置文件
$ sudo vi /etc/redis/redis.conf
#注释掉下面这一行。
# bind 127.0.0.1

配置密码登录

#编辑redis配置文件
$ sudo vi /etc/redis/redis.conf
#找到下面这一行并去除注释
# requirepass foobared #未修改之前
#修改之后,123456是设置的redis密码
requirepass 123456 

3、重启redis

$ sudo service redis-server restart
# 或者可以手动杀掉进程,再开启
$ sudo killall redis-server
$ sudo redis-server /etc/redis/redis.conf

可以在别的客户端中测试连接(客户端已经配置好redis)

# -h接redis服务器地址,-p端口号,-a密码
$ redis-cli -h 192.168.1.188 -p 6379 -a 123456

2、应用服务器安装php redis扩展

注意:如果redis使用频率不高,只是该项目使用,可以不用安装php的redis扩展,直接在对应的laravel项目安装predis扩展包(从开发编码实现那步开始)

==由于测试时我们以自己的电脑当应用服务器,以windows为例:==

(1)redis的php扩展下载地址:
http://windows.php.net/downlo...

根据自己的php版本和系统版本,下载对应的扩展包,解压
文件“php_redis-2.2.5-5.5-ts-vc11-x64.zip”是php5.5版本的。

(2)将解压文件中的php_redis.dll放到php的扩展目录ext下。

(3)在apache的php.ini配置文件下加上extension=php_redis.dll

(4)重启apache。

查看phpinfo是否有redis的扩展,如果有,则说明php-redis安装成功。

==以ubuntu为例==

$ sudo apt-get install php5-redis

重启apache

$ sudo /etc/init.d/apache2 restart

查看phpinfo是否有redis的扩展,如果有,则说明php5-redis安装成功。

3、开发编码实现

(1)需要安装predis扩展包

$ composer require "predis/predis:~1.0"

php artisan config:cache

(2)配置文件中.env中需要增加队列驱动的配置

QUEUE_DRIVER=redis
REDIS_HOST=192.168.1.188

(3)config/database.php配置redis的连接参数

'redis' => [

        'cluster' => false,

        'default' => [
            'host'     => env('REDIS_HOST', '127.0.0.1'),
            'port'     => 6379,
            'database' => 0,
            'password' => env('REDIS_PASSWORD', '123456')
        ],

    ],

(4)在appJobs中创建任务类,当队列处理该任务时执行的handle方法。
这里以我们实际代码为例:

<?php

namespace App\Jobs;

use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;

use App\Classes\LogisticApi\LogisticSdk\alibaba\AlibabaClient;

use Illuminate\Support\Facades\Redis;
/**
* 阿里巴巴无忧物流创建线上发货createWarehouseOrder后,
* 国际物流单号不是实时返回,需要间隔1-2分钟调用查询接口进行查询
* 此任务主要进行阿里getOnlineLogisticsInfo接口的查询
*/
class AligetOnlineLogisticsInfo extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;

    /**
    * 订单ID
    * @var string
    */
    protected $order_id;

    /**
    * api 账号信息
    * @var array
    */
    protected $api_account;

    /**
     * Create a new job instance.
     *
     * @param string $order_id  订单ID
     * @param string $seller_id 
     *
     * @return void
     */
    public function __construct($order_id, $api_account){
        $this->order_id    = $order_id;
        $this->api_account = $api_account;
    }

    /**
     * Execute the job.
     * 获取getOnlineLogisticsInfo物流信息
     *
     * @return void
     */
    public function handle(){

        $alibaba_client = new AlibabaClient($this->api_account);
        $response = $alibaba_client->getOnlineLogisticsInfo(['orderId' => $this->order_id]);
        print_r($response);
        //TODO 抓取失败后的处理,后续根据业务需求来处理

    }
}

(5)推送任务到队列。
使用了DispatchesJobs trait。该trait提供了一些允许你方便推送任务到队列的方法,例如dispatch方法。可以为任务指定队列,也可以延迟任务。
以我们实际业务为例:

namespace App\Classes\LogisticApi;

use App\Classes\LogisticApi\LogisticTrackingAbstract;

use App\Classes\LogisticApi\LogisticSdk\alibaba\AlibabaClient;
use App\Models\Erp_aliexpress_order_master;
use App\Models\Erp_aliexpress_order_slave;
use App\Models\Erp_logistics_setting;
use App\Models\Erp_aliexpress_token;

use Illuminate\Foundation\Bus\DispatchesJobs;
use App\Jobs\AligetOnlineLogisticsInfo;
/**
* ocs物流对接
*/
class logisticTrackingWuyou extends LogisticTrackingAbstract {

    use DispatchesJobs;
    /**
    *
    */
    public function __construct(){

    }

    /**
    * 获取tracking数据
    *
    * @param array $api_data   订单数据,可以是订单号之类的
    * @param array $api_param  接口参数数据
    * @param string $save_path 保存运单图片的路径
    *
    * @return array tracking
    */
    public function getTracking(array $api_data, array $api_param, $save_path){

        //得到订单信息
        $order = $this->getOrder($api_data['order_id']);
        //得到对应的订单账号信息
        $api_account = $this->getApiAccountInfo($order['seller_id']);

        $alibaba_client = new AlibabaClient($api_account);

        $params = $this->setCreateWarehouseOrderApiParams($order, $alibaba_client);

        if(isset($seller_address->error_code)){
            return $params;
        }

        $response = $alibaba_client->createWarehouseOrder($params);
        //成功了,推送队列任务获取getOnlineLogisticsInfo国际物流,
        //国际物流返回不是实时返回,需要等待1-2分钟
        if(true == $response->success){
            //推入getOnlineLogisticsInfo队列并延迟120秒执行
            $job = (new AligetOnlineLogisticsInfo($api_data['order_id'], $api_account))->delay(120);
            $this->dispatch($job);

        }

        return $response;

    }

}

==注意,由于我们没有正式的业务情景测试,所以使用单元测试,在测试之前,需要配置好单元测试的队列驱动,在phpunit.xml中,注意
以下QUEUE_DRIVER,需要将其改为redis,或者删掉。==

<env name="QUEUE_DRIVER" value="sync"/>

4、运行队列监听器

(1)应用服务器监听

如果之前有 php artisan config:cache 缓存配置,最好先把配置缓存清除:php artisan config:clear。

测试过程中,可以使用 ==php artisan queue:listen==进行监听。

线上可以使用 ==php artisan queue:work --daemon==

详细的监听方式可以查看:http://laravelacademy.org/pos...

(2)redis服务器监听

redis-cli连接redis后,可以使用==monitor==查看队列情况。

具体可以参考:

http://laravelacademy.org/pos...

http://laravelacademy.org/pos...


South
182 声望5 粉丝